#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include "log.hpp"

using namespace MyLog;

int main(int argc, char *argv[])
{
    if(argc != 3){
        std::cerr << "Uage-> " << argv[0] << "[ip]" << "[port]" << std::endl;
        return 1;
    }
    std::string ipaddr = argv[1];
    u_int16_t port = std::stoi(argv[2]);

    // 1.创建socket 打开网卡
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sockfd < 0){
        std::cerr << "create socket error" << std::endl;
        return 2;
    }
    
    // 2.客户端不需要显式绑定socket，由操作系统自动随机分配
    // 为什么不需要显式绑定呢？
    // 如果一个主机上的多个客户端绑定在了同一个端口下，这样就会导致一个客户端起来了，另一个就起不来
    // 所以操作系统为了避免，显式绑定导致端口号重复的情况，就有操作系统自己随机分别端口号，而ip地址一个主机上的都一样，操作系统也知道

    // 3.客户端向服务器发送报文，也就是请求
    // 发送时，得知道给谁发
    struct sockaddr_in where;
    bzero(&where, sizeof(where));
    where.sin_family = AF_INET;
    where.sin_port = htons(port);
    where.sin_addr.s_addr = inet_addr(ipaddr.c_str());
    while(true){
        std::string message;
        std::cout << "please enter# ";
        std::getline(std::cin, message);
        int n = sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr*)&where, sizeof(where));
        (void)n; // 这里暂时不对返回值进行判断

        // 客户端发送完报文后，继续接收从服务端发送回来的报文，以此来作为请求后处理的结果
        char buffer[1024];
        // 收报文的时候必须知道是谁发的
        struct sockaddr_in who;
        bzero(&who, sizeof(who));
        socklen_t who_size = sizeof(who);
        n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&who, &who_size);
        if(n > 0){
            buffer[n] = 0;
            LOG(loglevel::DEBUG) << buffer;
        }
    }

    return 0;
}